<template>
  <Codemirror
    v-if="props.type == 0"
    ref="cm"
    class="complier"
    v-model:value="userEditData.code"
    :options="cmOptions"
    border
  >
  </Codemirror>
  <codeMirrorFileTreeCM
    v-else
    :value="props.value"
    :language="props.language"
    @treeDataChange="
      (value) => {
        emit('valueChange', value);
      }
    "
  ></codeMirrorFileTreeCM>
</template>

<script setup>
import "codemirror/mode/javascript/javascript.js";
import Codemirror from "codemirror-editor-vue3";
import codeMirrorFileTreeCM from "./codeMirrorFileTreeCM.vue";
import "codemirror/theme/neat.css";
import "codemirror/theme/material-darker.css";
import "codemirror/theme/darcula.css";
import "codemirror/theme/3024-day.css";
import "codemirror/theme/elegant.css";
import "codemirror/mode/clike/clike.js";
import "codemirror/addon/selection/active-line";
import "codemirror/addon/fold/foldgutter.css";
import "codemirror/addon/fold/foldcode";
import "codemirror/addon/fold/foldgutter";
import "codemirror/addon/fold/brace-fold";
import "codemirror/addon/fold/comment-fold";
import "codemirror/addon/fold/markdown-fold";
import "codemirror/addon/fold/xml-fold";
import "codemirror/addon/fold/indent-fold";
import "codemirror/addon/search/match-highlighter";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/show-hint.js";
import "codemirror/addon/hint/anyword-hint";
import "codemirror/addon/edit/closebrackets";
import { onMounted, reactive, ref, watch } from "vue";
import { LangeuageConf } from "../config";
const props = defineProps({
  language: {
    type: String,
    default: "Java",
  },
  type: {
    type: Number,
    default: 0,
  },
  fontSize: {
    type: String,
    default: "16px",
  },
  value: {
    type: Object,
    default: () => {},
  },
  onlyRead: {
    type: Boolean,
    default: false,
  },
});
const emit = defineEmits(["valueChange"]);
/**
 * 字体大小
 */
watch(
  () => props.fontSize,
  (newVal) => {
    const codemirror = document.getElementsByClassName("CodeMirror")[0];
    codemirror.style.fontSize = newVal;
  }
);
const cm = ref();
/**
 * 切换语言模式
 */
watch(
  () => props.language,
  (newVal) => {
    if (["Java"].includes(newVal)) {
      cmOptions.mode = "text/x-java";
    } else if (["C With O2", "C"].includes(newVal)) {
      cmOptions.mode = "text/x-csrc";
    } else if (["C++ With O2", "C++"].includes(newVal)) {
      cmOptions.mode = "text/x-c++src";
    }
    if (cm.value) cm.value.cminstance.setOption("language", newVal);
    localStorage.setItem(`curLang`, newVal);
  }
);

/**
 * 配置项
 */
const cmOptions = reactive({
  tabSize: 4, // tab的空格个数
  theme: "3024-day", //主题样式
  lineNumbers: true, //是否显示行数
  lineWrapping: false, //是否自动换行
  viewportMargin: 50,
  styleActiveLine: true, //line选择是是否加亮
  matchBrackets: true, //括号匹配
  mode: "text/x-java", //实现javascript代码高亮
  readOnly: false, //只读
  extraKeys: {
    Ctrl: "autocomplete",
    Tab: (cm) => {
      if (cm.somethingSelected()) {
        // 存在文本选择
        cm.indentSelection("add"); // 正向缩进文本
      } else {
        // 无文本选择
        cm.replaceSelection(
          Array(cm.getOption("indentUnit") + 3).join(" "),
          "end",
          "+input"
        ); // 光标处插入 indentUnit 个空格
      }
    },
    ";": (cm) => {
      cm.replaceSelection(";");
    },
    ".": (cm) => {
      cm.replaceSelection(".");
    },
    ",": (cm) => {
      cm.replaceSelection(",");
    },
    "/": (cm) => {
      cm.replaceSelection("/");
    },
    "\\": (cm) => {
      cm.replaceSelection("\\");
    },
    "\-": (cm) => {
      cm.replaceSelection("\-");
    },
    "\=": (cm) => {
      cm.replaceSelection("\=");
    },
  },
  // 代码提示功能
  hintOptions: {
    // 避免由于提示列表只有一个提示信息时，自动填充
    completeSingle: false,
    // 不同的语言支持从配置中读取自定义配置 sql语言允许配置表和字段信息，用于代码提示
  },
  autoCloseBrackets: true, // 启用括号自动补全
  // 代码折叠
  gutters: [
    "CodeMirror-lint-markers",
    "CodeMirror-linenumbers",
    "CodeMirror-foldgutter",
  ],
  foldGutter: true, // 启用行槽中的代码折叠
});

/**
 * 用户数据
 */
const userEditData = reactive({
  code: "",
});

onMounted(() => {
  if (cm.value?.cminstance) {
    cm.value.cminstance.on("inputRead", (cmInstance, event) => {
      cmInstance.showHint();
    });
  }
  // if (props.type == 0 && props.onlyRead && props.value?.code?.length) {
  //   userEditData.code = props.value?.code[0]?.content || {};
  // }
});

watch(
  () => userEditData.code,
  (newVal) => {
    if (props.type == 0) {
      emit("valueChange", {
        code: [
          {
            fileName: LangeuageConf[props.value.language],
            content: newVal,
          },
        ],
        language: props.value.language,
        pid: props.value.pid,
      });
    }
  }
);
watch(
  () => props.value,
  () => {
    if (props.type == 0 && props.onlyRead && props.value?.code?.length) {
      userEditData.code = props.value?.code[0]?.content;
    }
  },
  {
    deep: true,
  }
);
</script>

<style lang="less" scoped></style>
